//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "DisProtAnalysis.h"

#include <iostream>
#include <fstream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGHTINLINE  100000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DisProtAnalysis::DisProtAnalysis() {
  
  this->filename   = new String ();
  this->idpResults = new TListE <DisProtProcessResult> ();
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DisProtAnalysis::DisProtAnalysis(const DisProtAnalysis& disProtAnalysis) {
  
  this->filename   = new String (disProtAnalysis.filename);
  this->idpResults = new TListE <DisProtProcessResult> (disProtAnalysis.idpResults);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DisProtAnalysis::DisProtAnalysis(const DisProtAnalysis* disProtAnalysis) {
  
  this->filename   = new String (disProtAnalysis->filename);
  this->idpResults = new TListE <DisProtProcessResult> (disProtAnalysis->idpResults);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DisProtAnalysis::~DisProtAnalysis() {
  
  if (this->filename)   delete this->filename;
  if (this->idpResults) delete this->idpResults;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void DisProtAnalysis::Filename(String* filename) {
  
  if (filename) this->filename->In(filename);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void DisProtAnalysis::IdpResults(TListE <DisProtProcessResult>* idpResults) {
  
  if (idpResults) *(this->idpResults) = *(idpResults);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* DisProtAnalysis::Filename(void) {
  
  return this->filename;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <DisProtProcessResult>* DisProtAnalysis::IdpResults(void) {
  
  return this->idpResults;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool DisProtAnalysis::ReadIDPFile(void) {
  
  if (!this->filename || !this->filename->Length()) return false;
  
  fstream fileIDPResults;
  fileIDPResults.open(this->filename->Out(), fstream::in);
  if (!fileIDPResults.is_open()) return false;
  
  char buffer[LENGHTINLINE + 1];
  int  count = 0;
  
  while (!fileIDPResults.eof()) {
    
    DisProtProcessResult* result = new DisProtProcessResult ();
    
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->IdInput(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->SequenceInput(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->SeqPredictionInput(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->ProbPredictionInput(buffer);
    
    this->idpResults->Add(result);
    
  }
  
  fileIDPResults.close();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool DisProtAnalysis::NumberSequencePerIDPsPercernt(String* filenameOut, int range) {
  
  if (!filenameOut || !filenameOut->Length() || !this->idpResults->Length()) return false;
  
  fstream fileOut;
  
  fileOut.open(filenameOut->Out(), fstream::out);
  
  if (!fileOut.is_open()) return false;
  
  int numberPartitions = 100/range;
  
  struct tablePercent {
    int    range;
    int    amountIDPPrediction;
  };
  
  struct tablePercent listPercentAmountIDP [numberPartitions];
  
  for (int i = 0; i < numberPartitions; i++) {
    listPercentAmountIDP[i].range               = ((i + 1)*range <= 100)?((i + 1)*range):100;
    listPercentAmountIDP[i].amountIDPPrediction  = 0;
  }
  
  this->idpResults->SetInitial();
  while (this->idpResults->SetNext()) {
    
    double percentIDPPredcition  = this->idpResults->GetCurrent()->ComputePercentIDPPrediction();
    
    for (int i = 0; i < numberPartitions; i++) 
      if (percentIDPPredcition  >= listPercentAmountIDP[i].range) listPercentAmountIDP[i].amountIDPPrediction++;
    
  }
  
  fileOut << "----------------------------------------------------------------------" << endl;
  fileOut << "|           Results of Intrinsic Protein Disorder Prediction         |" << endl;
  fileOut << "----------------------------------------------------------------------" << endl;
  fileOut << "|   Disordered by:    |     DisProt definition     |                 |" << endl;
  fileOut << "---------------------------------------------------| Total Sequences |" << endl;
  fileOut << "|    % of Disorder    |   Amount   |  % of Total   |                 |" << endl;
  fileOut << "----------------------------------------------------------------------" << endl;
  for (int i = 0; i < numberPartitions; i++) {
    
    fileOut << "| >";
    fileOut.width(18);
    fileOut.left;
    fileOut << listPercentAmountIDP[i].range;
    fileOut << "%";
    fileOut << "|";
    
    double pIDPLoopCoils = (double)(100) * (double)(listPercentAmountIDP[i].amountIDPPrediction) / (double)(this->idpResults->Length());
    
    fileOut.width(12);
    fileOut.right;
    fileOut << listPercentAmountIDP[i].amountIDPPrediction;
    fileOut << "|";
    
    fileOut.width(15);
    fileOut.right;
    fileOut << pIDPLoopCoils;
    fileOut << "|";
    
    fileOut.width(17);
    fileOut.right;
    fileOut << this->idpResults->Length();
    fileOut << "|";
    
    fileOut << endl;
    
  }
  
  fileOut << "----------------------------------------------------------------------" << endl;
  
  fileOut.close();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
